package psn.zjk.common.jdk;

import java.io.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @USER white
 * @DATETIME 2021/4/3 23:01
 */
public interface HelloService {

    String sayHello();

    BlockingQueue<String> CLASSES = new LinkedBlockingQueue<>();

    BlockingQueue<String> EVENTS = new LinkedBlockingQueue<>();

    AtomicBoolean START = new AtomicBoolean(false);

    static void main(String[] args) throws Exception {
        Thread thread = new Thread(() -> {
            ClassLoader loader = new ClassLoader() {

                @Override
                protected Class<?> findClass(String name) throws ClassNotFoundException {
                    String location = "DefaultHelloService1.class";
                    if (name.contains("DefaultHelloService2")) {
                        location = "DefaultHelloService2.class";
                    }
                    File classFile = new File(location);
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    try {
                        InputStream stream = new FileInputStream(classFile);
                        int b;
                        while ((b = stream.read()) != -1) {
                            outputStream.write(b);
                        }
                    } catch (IOException e) {
                        throw new IllegalArgumentException(e);
                    }
                    byte[] bytes = outputStream.toByteArray();
                    Class<?> defineClass = super.defineClass(name, bytes, 0, bytes.length);
                    try {
                        EVENTS.put(String.format("加载类成功,类名:%s", defineClass.getName()));
                    } catch (Exception ignore) {

                    }
                    return defineClass;
                }
            };
            Thread x = new Thread(() -> {
                try {
                    if (START.compareAndSet(false, true)) {
                        Thread y = new Thread(() -> {
                            try {
                                for (; ; ) {
                                    String event = EVENTS.take();
                                    System.out.println("接收到事件,事件内容:" + event);
                                }
                            } catch (Exception ignore) {

                            }
                        }, "Y");
                        y.setDaemon(true);
                        y.start();
                    }
                    for (; ; ) {
                        String take = CLASSES.take();
                        Class<?> klass = loader.loadClass(take);
                        HelloService helloService = (HelloService) klass.newInstance();
                        System.out.println(helloService.sayHello());
                    }
                } catch (Exception ignore) {

                }
            }, "X");
            x.setContextClassLoader(loader);
            x.setDaemon(true);
            x.start();
        });
        thread.start();
        CLASSES.put("club.throwable.loader.DefaultHelloService1");
        CLASSES.put("club.throwable.loader.DefaultHelloService2");
        Thread.sleep(5000);
        System.gc();
        Thread.sleep(5000);
        System.gc();
        Thread.sleep(Long.MAX_VALUE);
    }



}
